
/**
 * 任务锁，可用于接口请求的并行拦截、防抖处理
 * 
 * @class Lock
 * 
 * 加锁方式： 调用Lock实例的entry方法，并传入唯一标识hash值
 * 去锁方式： 1、调用Lock实例的remove方法，并传入唯一标识hash值
 *          2、调用Lock实例的entry方法返回值的remove方法，不需要传入任何值
 * 
    const lock = new Lock()
    const hash = "12345678"

    方式一：（推荐）
    lock.entry(hash)
    lock.remove(hash)

    方式二：
    const test = lock.entry(hash)
    test.remove()
    test = null //方式二建议增加这步，减少内存占用
 *
 */

class Lock{

    constructor() {
        this.map = new Map()
        this.config = {
            //此参数控制是否自动移除锁
            autoRemove: false,
            //自动移除锁时间（ms）
            removeTime: 1000
        }
    }

    entry(hash, config) {

        let selfConfig = null

        if (!hash) return console.warn("hash值不能为空.")

        if (this.has(hash)) return console.warn("已被lock程序锁止.")

        if (Object.prototype.toString.call(config) == '[object Object]') {
            selfConfig = { ...this.config, ...config }
        }

        if (selfConfig.autoRemove === true) {
            this.startAutoRemove(hash, selfConfig.removeTime)
        }
            
        this.map.set(hash, 1)
        return {
            hash,
            remove: this.remove.bind(this, hash)
        }
    }

    has(hash) {
        return this.map.has(hash)
    }

    remove(hash) {
        this.map.delete(hash)
    }

    startAutoRemove(hash, time) {
        setTimeout(() => {
            this.remove(hash)
        }, time)
    }
    
}